<template>
  <div class="core-container">
    <!-- :list="designer.widgetList" -->
    <draggable
      :list="widgetList"
      item-key="id"
      v-bind="{ group: 'dragGroup', ghostClass: 'ghost', animation: 400 }"
      tag="div"
      :component-data="{ name: 'fade', class: 'canvas-drag-drop-zone' }"
      handle=".drag-handler"
      @end="onDragEnd"
      @add="onDragAdd"
      @update="onDragUpdate"
      :move="checkMove"
    >
      <template #item="{ element: widget, index }">
        <div class="form-widget-list mb-4">
          <template v-if="'container' === widget.category">
            <!-- 容器组件 -->
            <component
              :is="widget.name + 'Source'"
              readonly
              :key="widget.id"
              :id="widget.id"
              :config="widget.props"
              :sub="widget.subWidgets"
              :widget="widget"
              @subChange="handleSubChange"
              @select="handleSelect"
            ></component>
          </template>

          <template v-else>
            <!-- 字段组件 -->
            <component
              :is="widget.name + 'Source'"
              readonly
              :id="widget.id"
              :key="widget.id"
              :config="widget.props"
              @select="handleSelect"
            ></component>
          </template>
        </div>
      </template>
    </draggable>
  </div>
</template>

<script lang="ts" setup>
import { sourceConfig } from '@/views/LowDesigner/source-config.ts'
import { ref } from 'vue'
import { generateId, findTreeNode } from '@/util/index.ts'
import cloneDeep from 'lodash/cloneDeep'

const emits = defineEmits<{
  (e: 'active', value: any, instance: any): void
  (e: 'update', value: any): void
  (e: 'json', value: any): void
  (e: 'select', value: any): void
}>()

const widgetList = ref<WidgetConfig[]>([])

function onDragEnd() {
  console.log('drag end')
}

function onDragUpdate() {
  console.log('onDragUpdate')
}

function onDragAdd(evt: any) {
  const oldIndex = evt.oldIndex // 拖动前在老容器中排第几
  const { sourceType } = evt.from.__draggable_component__.componentData
  const module: any = sourceConfig.find((item) => item.sourceType === sourceType)
  const transComponent = module.widgetList[oldIndex]
  // 深拷贝
  const cloneComponent = cloneDeep(transComponent)
  cloneComponent.id = cloneComponent.name + '-' + generateId()

  // 如果含有子组件，则遍历子组件给id,只做一层;
  // 这里已经是克隆出来的新对象了。给id这个事最好在这里给了，不然去里面又深拷贝一次？
  if (cloneComponent.subWidgets && cloneComponent.subWidgets.length) {
    cloneComponent.subWidgets.forEach((item: any) => {
      item.id = item.name + '-' + generateId()
    })
  }

  widgetList.value.push(cloneComponent)

  emits('update', cloneDeep(widgetList.value))
  emits(
    'active',
    {
      sourceType: sourceType,
      oldIndex: oldIndex,
      cmpId: cloneComponent.id,
    },
    cloneComponent,
  )
  emits('json', cloneDeep(widgetList.value))
}

function handleSubChange(params: any) {
  if (params.type == 'addRow') {
    const theWidget = widgetList.value.find((item) => item.id == params.id)
    theWidget?.subWidgets.push(params.value)
  }
  emits('update', cloneDeep(widgetList.value))
  emits('json', cloneDeep(widgetList.value))
  emits('select', params.value)
}

function checkMove() {
  console.log('checkMove')
}

function getWidgetName(obj: WidgetType) {
  return obj.type
}

function handleSelect(widgetId: string) {
  const theWidget = findTreeNode(widgetList.value, widgetId)
  emits('select', theWidget)
}

// 修改整个列表
function updateWidgetList() {}

// 修改某个组件
function updateWidget(params: any, activeCmpId: string) {
  const theWidget: any = findTreeNode(widgetList.value, activeCmpId)
  theWidget.props = params
  emits('json', cloneDeep(widgetList.value))
}

/** 根据json 生成组件 */
function loadComponentByJson(modelJson: any) {
  const cloneComponent = cloneDeep(modelJson)
  cloneComponent.id = cloneComponent.name + '-' + generateId()
  // 如果含有子组件，则遍历子组件给id,只做一层;
  // 这里已经是克隆出来的新对象了。给id这个事最好在这里给了，不然去里面又深拷贝一次？
  if (cloneComponent.subWidgets && cloneComponent.subWidgets.length) {
    cloneComponent.subWidgets.forEach((item: any) => {
      item.id = item.name + '-' + generateId()
    })
  }
  widgetList.value.push(cloneComponent)
  emits('update', cloneDeep(widgetList.value))
  emits(
    'active',
    {
      sourceType: 'Business',
      oldIndex: 1,
      cmpId: cloneComponent.id,
    },
    cloneComponent,
  )
  emits('json', cloneDeep(widgetList.value))
}

defineExpose({
  updateWidgetList,
  updateWidget,
  loadComponentByJson,
})
</script>

<style lang="scss" scoped>
.core-container {
  height: 100%;
  border-bottom: 1px solid #dcdfe6;
  padding: 10px;
}

.canvas-drag-drop-zone {
  height: 100%;
}
</style>
